﻿#region  
//=====================================================
// 文件名: ReourceManager                
// 创建者: #AuthorName#                
// 创建时间: #CreateTime#              	
// Email: #AuthorEmail#               
// 描述: 当前脚本的功能              
// 修改者列表: 修改者名字以及修改功能      
// 版权所有: #Copyright#                 
//======================================================
#endregion 



using FrameWork.AB;
using FrameWork.ObjectPool;
using FrameWork.Reource;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace FrameWork
{

    public delegate void OnAsyncObjFinish(string path, Object obj, params object[] parme);

    public class ResourceManager : Singleton<ResourceManager>
    {
        private bool isEditorModel;

        private IResourceLoad m_ReourceLoad;

        public bool IsEditorModel { get => isEditorModel; set => isEditorModel = value; }




        public ResourceManager()
        {
            IsEditorModel = Application.isEditor;
            m_ReourceLoad = IsEditorModel == false ? new AssetBundleLoadReource() : new EditorLoadReource() as IResourceLoad;
#if UNITY_EDITOR
            m_ReourceLoad = new AssetBundleLoadReource();
            //m_ReourceLoad = new EditorLoadReource();
#endif
        }

        public T LoadResource<T>(string path) where T : Object
        {
            return m_ReourceLoad.LoadResource<T>(path);
        }

        public ResourceItem GetCacheResourceItem(uint _crc, int _addrefcount = 1)
        {
            return m_ReourceLoad.GetCacheResourceItem(_crc, _addrefcount);
        }

        public void CacheResource(string _path, ref ResourceItem _item, uint _crc, Object _obj, int _addrefcount = 1)
        {
            m_ReourceLoad.CacheResource(_path, ref _item, _crc, _obj, _addrefcount);
        }

        public void WashOut()
        {
            m_ReourceLoad.WashOut();
        }

        public bool ReleaseResource(Object obj, bool destoryObj = false)
        {
            return m_ReourceLoad.ReleaseResource(obj, destoryObj);
        }

        public void DestoryResourceItem(ResourceItem item, bool destoryCache = false)
        {
            m_ReourceLoad.DestoryResourceItem(item, destoryCache);
        }

        public void PreloadRes(string path)
        {
            m_ReourceLoad.PreloadRes(path);
        }

        public void Clear()
        {
            m_ReourceLoad.Clear();
        }

        /*==========================================================异步加载=================================================================*/

        public void AsyncLoadResource<T>(string path, OnAsyncObjFinish dealfinish, LoadResPriority priority, uint crc = 0, params object[] param)
        {
            m_ReourceLoad.AsyncLoadResource<T>(path, dealfinish, priority, crc, param);
        }

        public void Init(MonoBehaviour mono)
        {
            m_ReourceLoad.Init(mono);
        }

    }
        public class DoubleLinkedistNode<T> where T : class, new()
        {
            public DoubleLinkedistNode<T> FrontNode = null;
            public DoubleLinkedistNode<T> NextNode = null;
            public T CurrentNode = null;
        }

        public class DoubleLinkedlist<T> where T : class, new()
        {
            public DoubleLinkedistNode<T> FirstNode = null;
            public DoubleLinkedistNode<T> EndNode = null;
            protected CalssObjectPool<DoubleLinkedistNode<T>> m_LinkedlistPool = ObjectManager.Instance.GetOrCreateObjectPool<DoubleLinkedistNode<T>>(500);
            protected int m_count = 0;
            public int Count => m_count;

            public DoubleLinkedistNode<T> AddToFirstNode(T t)
            {
                DoubleLinkedistNode<T> node = m_LinkedlistPool.Spawn(true);
                node.NextNode = null;
                node.FrontNode = null;
                node.CurrentNode = t;
                return AddToFirstNode(node);
            }

            public DoubleLinkedistNode<T> AddToFirstNode(DoubleLinkedistNode<T> node)
            {
                if (node == null) return null;
                node.FrontNode = null;
                if (FirstNode == null)
                {
                    FirstNode = EndNode = node;
                }
                else
                {
                    node.NextNode = FirstNode;
                    FirstNode.FrontNode = node;
                    FirstNode = node;
                }
                m_count++;
                return FirstNode;
            }

            public DoubleLinkedistNode<T> AddToEndNode(T t)
            {
                DoubleLinkedistNode<T> node = m_LinkedlistPool.Spawn(true);
                node.FrontNode = null;
                node.NextNode = null;
                node.CurrentNode = t;
                return AddToEndNode(node);
            }

            public DoubleLinkedistNode<T> AddToEndNode(DoubleLinkedistNode<T> node)
            {
                if (node == null)
                {
                    return null;
                }

                node.NextNode = null;
                if (EndNode == null)
                {
                    FirstNode = EndNode = node;
                }
                else
                {
                    node.FrontNode = EndNode;
                    EndNode.NextNode = node;
                    EndNode = node;
                }
                m_count++;
                return EndNode;
            }

            public void RemoveNode(DoubleLinkedistNode<T> node)
            {
                if (node == null) return;

                if (node == FirstNode)
                    FirstNode = node.NextNode;


                if (node == EndNode)
                    EndNode = node.FrontNode;


                if (node.FrontNode != null)
                    node.FrontNode.NextNode = node.NextNode;

                if (node.NextNode != null)
                    node.NextNode.FrontNode = node.FrontNode;

                node.FrontNode = node.NextNode = null;
                node.CurrentNode = null;

                m_LinkedlistPool.Recycle(node);
                m_count--;
            }

            public void MoveToFirst(DoubleLinkedistNode<T> node)
            {
                if (node == null || node == FirstNode)
                    return;

                if (node.FrontNode == null && node.NextNode == null)
                    return;

                if (node == EndNode)
                    EndNode = node.FrontNode;

                if (node.FrontNode != null)
                    node.FrontNode.NextNode = node.NextNode;

                if (node.NextNode != null)
                    node.NextNode.FrontNode = node.FrontNode;

                node.FrontNode = null;
                node.NextNode = FirstNode;
                FirstNode.FrontNode = node;
                FirstNode = node;

                if (EndNode == null)
                {
                    EndNode = FirstNode;
                }
            }
        }

        public class CMapList<T> where T : class, new()
        {
            private DoubleLinkedlist<T> m_DLink = new DoubleLinkedlist<T>();
            private Dictionary<T, DoubleLinkedistNode<T>> m_FindMap = new Dictionary<T, DoubleLinkedistNode<T>>();

            ~CMapList()
            {
                Clear();
            }

            public int NodeCount => m_DLink.Count;

            public bool Exist(T t)
            {
                return m_FindMap.TryGetValue(t, out DoubleLinkedistNode<T> node) && node != null;
            }

            public void InsertToHead(T t)
            {
                if (m_FindMap.TryGetValue(t, out DoubleLinkedistNode<T> node) && node != null)
                {
                    m_DLink.AddToFirstNode(node);
                    return;
                }
                m_DLink.AddToFirstNode(t);
                m_FindMap.Add(t, m_DLink.FirstNode);
            }

            public void PopInFromTheTail()
            {
                if (m_DLink.EndNode != null)
                {
                    Remove(m_DLink.EndNode.CurrentNode);
                }
            }

            public void Remove(T t)
            {
                if (!m_FindMap.TryGetValue(t, out DoubleLinkedistNode<T> node) || node == null)
                {
                    return;
                }

                m_DLink.RemoveNode(node);
                m_FindMap.Remove(t);
            }

            public T GetTailNode()
            {
                return m_DLink.EndNode == null ? null : m_DLink.EndNode.CurrentNode;
            }

            public bool RefreshNodeToFront(T t)
            {
                if (!m_FindMap.TryGetValue(t, out DoubleLinkedistNode<T> node) || node == null)
                    return false;

                m_DLink.MoveToFirst(node);
                return true;
            }

            public void Clear()
            {
                while (m_DLink.EndNode != null)
                {
                    Remove(m_DLink.EndNode.CurrentNode);
                }
            }

        }
    
}